#include "cprescheduling.h"
#include "cjgprocessschedule.h"
#include "cschdatacollector.h"
#include "global.h"


CPreScheduling::CPreScheduling() {}

CJgOrderProcess * CPreScheduling::GetProcessWorkingByPosition(int pos)
{
    if (pos < 1)return nullptr;
    if (pos > gTotalPositionNum)return nullptr;
    //CJgPosition posObj = theApp.pRIR->pPositionManager->getPosition(pos);
    //if (posObj.miPosNum != pos)return nullptr;
    int pStatus = 0;
    int pType = 0;
    bool pEnable = false;
    bool pStop = false;
    QString pWorkernum;
    QString pWaitBox;
    QString pInProBox;
    if (processPos->pPositionManager->getMoreStatus(pos, pStatus, pType, pEnable, pStop,
                                                     pWorkernum, pWaitBox, pInProBox) == false)
    {
        return nullptr;
    }

    //if (pSchData->pPositions.count() < pos)return nullptr;
    //SPOSITION * pPos = pSchData->pPositions[pos - 1];
    if (pStatus != IN_PRO_ONLY_P_S &&
        pStatus != WAITING_FOR_ONLY_PRO_P_S &&
        pStatus != BUSY_P_S &&
        pStatus != IN_THE_WAY_P_S &&
        pInProBox.isEmpty() &&
        pWaitBox.isEmpty()
        )
    {
        return nullptr;
    }


    CJgBoxData *pBox = nullptr;
    if (pStatus == IN_PRO_ONLY_P_S)
    {
        pBox = CSchDataCollector::FindBoxByNum(pSchData, pInProBox);
        if (pBox == nullptr)return nullptr;
        if (pBox->miBoxStatus != IN_PRO_B_S)return nullptr;
        if (pBox->miCurReworkRecordId > 0)return nullptr;
        if (pBox->mbRedistributeFlag)return nullptr;
    }
    else if(pStatus == WAITING_FOR_ONLY_PRO_P_S)
    {
        pBox = CSchDataCollector::FindBoxByNum(pSchData, pWaitBox);
        if (pBox == nullptr)return nullptr;
        if (pBox->miBoxStatus != WAITING_FOR_PRO_B_S)return nullptr;
        if (pBox->miCurReworkRecordId > 0)return nullptr;
        if (pBox->mbRedistributeFlag)return nullptr;
    }
    else if (pStatus == BUSY_P_S)
    {
        bool bBuff = false;
        if (false == pWaitBox.isEmpty())
        {
            pBox = CSchDataCollector::FindBoxByNum(pSchData, pWaitBox);
            if (pBox == nullptr)return nullptr;
            if (pBox->miBoxStatus != WAITING_FOR_PRO_B_S)return nullptr;
            if ((pBox->miCurReworkRecordId > 0) || (pBox->mbRedistributeFlag == true))
            {
                pBox = nullptr;
            }
            else
            {
                bBuff = true;
            }
        }
        if(false == bBuff)
        {
            pBox = CSchDataCollector::FindBoxByNum(pSchData, pInProBox);
            if (pBox == nullptr)return nullptr;
            if (pBox->miBoxStatus != IN_PRO_B_S)return nullptr;
            if ((pBox->miCurReworkRecordId > 0) || (pBox->mbRedistributeFlag == true))
            {
                return nullptr;
            }
        }
    }
    else if (pStatus == IN_THE_WAY_P_S)
    {
        bool bBuff = false;
        for (QVector<CJgOrder *> vOrderOneGroup : pSchData->OrderGroupByDeadLine)
        {
            //1.0、循环每个货期里面的订单
            for (CJgOrder * vOrder : vOrderOneGroup)
            {
                //2.0、循环每个部件
                for (QVector<CJgBoxData *> pBoxs : vOrder->mCurBoxSetGroupByPart)
                {
                    //3.0、循环每个筐
                    for (CJgBoxData * pBoxTemp : pBoxs)
                    {
                        if (pBoxTemp->miBoxStatus == SEND_PRO_B_S)
                        {
                            int iP = pBoxTemp->mStatusInfo.toInt();
                            if (iP > 0 && iP < gTotalPositionNum)
                            {
                                if (iP == pos)
                                {
                                    pBox = pBoxTemp;
                                    break;
                                }
                            }
                        }
                    }
                    if (pBox)break;
                }
                if (pBox)break;
            }
            if (pBox)break;
        }
        if (pBox)
        {
            if (pBox->miBoxStatus != WAITING_FOR_PRO_B_S)return nullptr;
            if ((pBox->miCurReworkRecordId > 0) || (pBox->mbRedistributeFlag == true))
            {
                pBox = nullptr;
            }
            else
            {
                bBuff = true;
            }
        }
        if (false == bBuff)
        {
            if (false == pWaitBox.isEmpty())
            {
                pBox = CSchDataCollector::FindBoxByNum(pSchData, pWaitBox);
                if (pBox == nullptr)return nullptr;
                if (pBox->miBoxStatus != WAITING_FOR_PRO_B_S)return nullptr;
                if ((pBox->miCurReworkRecordId > 0) || (pBox->mbRedistributeFlag == true))
                {
                    pBox = nullptr;
                }
                else
                {
                    bBuff = true;
                }
            }
        }
        if (false == bBuff)
        {
            pBox = CSchDataCollector::FindBoxByNum(pSchData, pInProBox);
            if (pBox == nullptr)return nullptr;
            if (pBox->miBoxStatus != IN_PRO_B_S)return nullptr;
            if ((pBox->miCurReworkRecordId > 0) || (pBox->mbRedistributeFlag == true))
            {
                return nullptr;
            }
        }


    }
    else if (!pWaitBox.isEmpty())
    {
        pBox = CSchDataCollector::FindBoxByNum(pSchData, pWaitBox);
        if (pBox == nullptr)return nullptr;
        if (pBox->miBoxStatus != WAITING_FOR_PRO_B_S)return nullptr;
        if (pBox->miCurReworkRecordId > 0)return nullptr;
        if (pBox->mbRedistributeFlag)return nullptr;
    }
    else if (!pInProBox.isEmpty())
    {
        pBox = CSchDataCollector::FindBoxByNum(pSchData, pInProBox);
        if (pBox == nullptr)return nullptr;
        if (pBox->miBoxStatus != IN_PRO_B_S)return nullptr;
        if (pBox->miCurReworkRecordId > 0)return nullptr;
        if (pBox->mbRedistributeFlag)return nullptr;
    }
    if (pBox == nullptr)return nullptr;

    return CSchDataCollector::FindProcessByOrderPartSeq(pSchData, pBox);
}

//计算小时任务数
bool CPreScheduling::CalcuteTarget(CJgOrder * pOrder)
{
    qDebug() << "进入CalcuteTarget方法";
    
    if (pOrder->isDepandencyError)
    {
        qDebug() << "订单依赖关系错误";
        for (QVector<CJgOrderProcess *> processes : pOrder->mOrderProcessSetGroupByPart)
        {
            for (CJgOrderProcess * pOp : processes)
            {
                if (pOp->mScheduling)
                {
                    pOp->mScheduling->mPlanHourTarget = 0;
                    pOp->mScheduling->mNowHourTarget = 0;
                }
            }
        }
        return false;
    }

    qDebug() << "创建subFlow对象";
    subFlow flow;

    //1、计算从投产到交付时间（秒）tSP
    qDebug() << "获取订单完成时间";
    qlonglong tSP = pOrderManager->getSecond2Finishu(pOrder->mLocalOrderNum);//SINGLEBASEDATAOBJ.mHolidaySetOpt.DiffSeconds(pOrder->mTimeOfOperation, pOrder->mDeadLine);
    qDebug() << "订单完成时间:" << tSP;
    //pOrder->miNow2DeadlineSecs;
    //2、计算从投产到当前的时间（秒）延后一小时，tSN
    qDebug() << "获取订单当前时间";
    qlonglong tSN = pOrderManager->getSecond2now(pOrder->mLocalOrderNum);//SINGLEBASEDATAOBJ.mHolidaySetOpt.DiffSeconds(pOrder->mTimeOfOperation, QDateTime::currentDateTime());
    qDebug() << "订单当前时间:" << tSN;
    /*if (tSP < (tSN + 3600))
    {
        tSN = tSP;
    }
    else
    {
        tSN += 3600;
    }*/
    tSN += 3600 * gRuleHourTargetWindow;

    //3、构建流程数据
    qDebug() << "构建流程数据，依赖步骤数量:" << pOrder->DepandencySteps.size();
    for (QSet<CJgDepandency*>* psd : pOrder->DepandencySteps)
    {
        qDebug() << "处理依赖步骤，步骤大小:" << psd->size();
        QSet<CJgDepandency*>* pSD = new QSet<CJgDepandency*>;
        for (CJgDepandency* pd : *psd)
        {
            qDebug() << "添加依赖对象到步骤";
            pSD->insert(pd);
        }
        flow.router.append(pSD);
    }

    qDebug() << "流程数据构建完成";

    //4、计算最大筐件数
    int MaxCnt = 0;
    int BoxCnt = 0;
    qDebug() << "计算最大筐件数，部件数量:" << pOrder->mCurBoxSetGroupByPart.size();
    for (QVector<CJgBoxData *> boxes : pOrder->mCurBoxSetGroupByPart)
    {
        qDebug() << "处理部件筐数据，筐数量:" << boxes.size();
        for (CJgBoxData * pBox : boxes)
        {
            MaxCnt += pBox->miPlanCnt;
            BoxCnt++;
        }
    }
    if (BoxCnt == 0)
    {
        MaxCnt = 5;
    }
    else
    {
        MaxCnt = (BoxCnt + MaxCnt - 1) / BoxCnt;
    }
    if (MaxCnt > pOrder->miTotalPlanCnt)
    {
        MaxCnt = pOrder->miTotalPlanCnt;
    }

    qDebug() << "最大筐件数:" << MaxCnt;

    qDebug() << "调用flow.split()";
    flow.split();
    qDebug() << "flow.split()调用完成";
    //if (pOrder->mLocalOrderNum == "20240331001022")
    //{
    //	qDebug() << "总时间：" << tSP << ",当前时间：" << tSN;
    //}
    qDebug() << "调用flow.getSTD()";
    flow.getSTD();
    qDebug() << "flow.getSTD()调用完成";
    float rate = gFeedCyclePercent;
    qDebug() << "调用flow.setTime()";
    flow.setTime(0, tSP, MaxCnt, rate);
    qDebug() << "flow.setTime()调用完成";
    qDebug() << "调用flow.outProcessTime()";
    flow.outProcessTime(pOrder->miTotalPlanCnt, tSN);
    qDebug() << "flow.outProcessTime()调用完成";
    if (gRuleStartRateRefix)
    {
        //允许进行修正
        float fMaxSTD = 0;
        fMaxSTD = flow.getMaxSTDbyProcess();
        int iMinDuty = flow.getMinOperationTimeByProcess();
        if (iMinDuty > (fMaxSTD * pOrder->miTotalPlanCnt * rate))
        {
            rate = (tSP * 1.0) / (flow.totalSTD*MaxCnt + fMaxSTD * pOrder->miTotalPlanCnt);
            flow.setTime(0, tSP, MaxCnt, rate);
            flow.outProcessTime(pOrder->miTotalPlanCnt, tSN);
            //qDebug() << "订单" << pOrder->mLocalOrderNum << "修正斜率"<< rate;
        }
    }
    qDebug() << "CalcuteTarget方法执行完成";
    return true;
}

subFlow::subFlow(subFlow * vParent)
{
    parent = vParent;
    iStartSec = 0;
    iEndSec = 0;
    iAvgCnt = 1;
    totalSTD = 0;
    iFirstBox = 0;
    from = nullptr;
    if (vParent)
    {
        iStartSec = vParent->iStartSec;
        iEndSec = vParent->iEndSec;
        iAvgCnt = vParent->iAvgCnt;
        totalSTD = vParent->totalSTD;
        iFirstBox = vParent->iFirstBox;
        if (false == vParent->partName.isEmpty())
        {
            partName = vParent->partName;
        }
    }
}


subFlow::~subFlow()
{
    // 删除router中的依赖集合
    for (QSet<CJgDepandency*> *psd : router)
    {
        delete psd;
    }
    router.clear();
    
    // 删除子流程对象
    for (QSet<subFlow *> s : children)
    {
        for (subFlow * f : s)
        {
            // 删除所有子对象，因为每个subFlow对象都应该负责删除自己创建的子对象
            if (f) {
                delete f;
            }
        }
        s.clear();
    }
    children.clear();
}

bool subFlow::split()
{
    qDebug() << "进入split方法，partName:" << partName;
    if (partName.isEmpty())
    {
        qDebug() << "调用splitByPart";
        splitByPart();
    }
    else
    {
        qDebug() << "调用splitByMerge";
        splitByMerge();
    }

    qDebug() << "处理子流程，子流程数量:" << children.size();
    for (int i = 0; i < children.size(); i++) {
        QSet<subFlow *> s = children.at(i);
        qDebug() << "处理子流程集合" << i << "，集合大小:" << s.size();
        for (subFlow * f : s)
        {
            if (f != nullptr) {
                // 添加递归深度检查，防止无限递归
                static int recursionDepth = 0;
                if (recursionDepth > 100) {  // 设置最大递归深度限制
                    qDebug() << "警告：递归深度超过限制，防止死循环";
                    break;
                }
                recursionDepth++;
                qDebug() << "递归调用子流程split，当前深度:" << recursionDepth;
                f->split();
                recursionDepth--;
            } else {
                qDebug() << "发现空子流程指针，跳过";
            }
        }
    }
    qDebug() << "split方法执行完成";
    return true;
}

bool subFlow::splitByPart()
{
    qDebug() << "进入splitByPart方法";
    //先检查有没有二次合筐工序，顺便把所有部件名拿到
    bool hasECHK = false;
    QSet<QString> partNames;
    for (QSet<CJgDepandency*>* psd : router)
    {
        if (psd == nullptr) {
            qDebug() << "发现空的依赖步骤指针";
            continue;
        }
        
        for (CJgDepandency* pd : *psd)
        {
            if (pd == nullptr) {
                qDebug() << "发现空的依赖对象指针";
                continue;
            }
            
            if (pd->curProcess)
            {
                if (pd->curProcess->mProcessBrief == SECONDPACKUP_PROCESS)
                {
                    hasECHK = true;
                }
                partNames.insert(pd->curProcess->mPartName);
            }
        }
    }
    
    // 添加迭代计数器防止死循环
    int iterationCount = 0;
    const int maxIterations = 100;
    
    if (hasECHK)
    {
        qDebug() << "检测到二次合筐工序";
        //有的话分出来前后幅组件组成的子流程，其他部件组成的子流程，合并到组件组成的子流程，后道组成的子流程
        QHash<QString,subFlow *> hsf;
        QHash<QString, QSet<CJgDepandency*>*>hsStep;

        int HK = 0;//0=还没有到合筐，1=二次合筐步骤，2=已经合筐不需要添加流程，3=已合筐后需要添加子流程
        QSet<QString> partLinShi;
        for (QSet<CJgDepandency*>* psd : router)
        {
            // 检查迭代次数，防止死循环
            if (++iterationCount > maxIterations) {
                qDebug() << "警告：splitByPart达到最大迭代次数，防止死循环退出";
                break;
            }
            
            if (psd == nullptr) continue;
            
            hsStep.clear();
            for (CJgDepandency* pd : *psd)
            {
                if (pd == nullptr) continue;
                
                //qDebug() << pd->Desp();
                QString part;
                if ((pd->PartName == ZJ_VALUE) || (pd->PartName == QF_VALUE) || (pd->PartName == HF_VALUE))
                {
                    if (pd->curProcess && pd->curProcess->mProcessBrief == SECONDPACKUP_PROCESS)
                    {
                        HK = 1;
                        break;
                    }
                    if (HK == 0)
                    {
                        if (!hsf.contains("临时"))
                        {
                            subFlow * f = new subFlow(this);
                            f->partName = "临时";
                            hsf["临时"] = f;
                        }
                        part = "临时";
                    }
                    else// if (HK == 2)
                    {
                        if (!hsf.contains(ZJ_VALUE))
                        {
                            subFlow * f = new subFlow(this);
                            f->partName = ZJ_VALUE;
                            hsf.clear();
                            partLinShi.clear();
                            hsf[ZJ_VALUE] = f;
                            HK = 3;
                        }
                        part = ZJ_VALUE;
                    }
                }
                else
                {
                    if (HK == 0)
                    {
                        if (!hsf.contains(pd->PartName))
                        {
                            subFlow * f = new subFlow(this);
                            f->partName = pd->PartName;
                            //hsf.clear();
                            //partLinShi.clear();
                            hsf[pd->PartName] = f;
                            //if (HK == 2)
                            //{
                            //	HK = 3;
                            //}
                        }
                    }
                    else
                    {
                        if (!hsf.contains(pd->PartName))
                        {
                            subFlow * f = new subFlow(this);
                            f->partName = pd->PartName;
                            hsf.clear();
                            partLinShi.clear();
                            hsf[pd->PartName] = f;
                            if (HK == 2)
                            {
                                HK = 3;
                            }
                        }
                    }
                    //curF = hsf[pd->PartName];
                    part = pd->PartName;
                }
                if (false == hsStep.contains(part))
                {
                    QSet<CJgDepandency*> *pSD = new QSet<CJgDepandency*>;
                    hsStep[part] = pSD;
                }
                hsStep[part]->insert(pd);
                partLinShi.insert(part);
            }
            if (HK == 0)
            {
                //步骤里的每一个工序已经加入到集合了，把他加到流程的步数
                for (QString vpart : partLinShi)
                {
                    if (hsStep.contains(vpart))
                    {
                        hsf[vpart]->router.append(hsStep[vpart]);
                    }
                }
            }
            else if (HK == 1)
            {
                //到二次合筐，所有部件名认为是一条并行的路径
                if (hsf.contains("临时")) {
                    hsf["临时"]->partName = "";
                }
                QSet<subFlow *> cSet;
                for (auto it = hsf.begin(); it != hsf.end(); ++it) {
                    if (it.value() != nullptr) {
                        cSet.insert(it.value());
                    }
                }
                children.append(cSet);
                hsf.clear();
                partLinShi.clear();
                HK = 2;
            }
            else if (HK == 2)
            {
                //已经合筐不需要添加流程
                for (QString vpart : partLinShi)
                {
                    if (hsStep.contains(vpart))
                    {
                        if (hsf.contains(vpart)) {
                            hsf[vpart]->router.append(hsStep[vpart]);
                        }
                    }
                }
            }
            else
            {
                //3 = 已合筐后需要添加子流程
                for (QString vpart : partLinShi)
                {
                    if (hsStep.contains(vpart))
                    {
                        if (hsf.contains(vpart)) {
                            hsf[vpart]->router.append(hsStep[vpart]);
                        }
                    }
                }
                QSet<subFlow *> cSet;
                for (auto it = hsf.begin(); it != hsf.end(); ++it) {
                    if (it.value() != nullptr) {
                        cSet.insert(it.value());
                    }
                }
                children.append(cSet);
                HK = 2;
            }
        }
    }
    else
    {
        qDebug() << "未检测到二次合筐工序";
        //没有的话分出部件组成的子流程和组件组成的子流程
        QHash<QString, subFlow *> hsf;
        QHash<QString, QSet<CJgDepandency*>*>hsStep;
        int YXBJ = 0;//有新部件之后立即放到子流程里，再有新部件的时候直接加入就好
        QSet<QString> partLinShi;
        for (QSet<CJgDepandency*> *psd : router)
        {
            // 检查迭代次数，防止死循环
            if (++iterationCount > maxIterations) {
                qDebug() << "警告：splitByPart达到最大迭代次数，防止死循环退出";
                break;
            }
            
            if (psd == nullptr) continue;
            
            hsStep.clear();
            for (CJgDepandency* pd : *psd)
            {
                if (pd == nullptr) continue;
                
                //qDebug() << pd->Desp();
                QString part;
                if (!hsf.contains(pd->PartName))
                {
                    if (YXBJ == 0)
                    {
                        hsf.clear();
                        partLinShi.clear();
                    }
                    subFlow * f = new subFlow(this);
                    f->partName = pd->PartName;
                    hsf[pd->PartName] = f;
                    YXBJ = 1;
                }
                part = pd->PartName;
                if (false == hsStep.contains(part))
                {
                    QSet<CJgDepandency*> *pSD = new QSet<CJgDepandency*>;
                    hsStep[part] = pSD;
                }
                hsStep[part]->insert(pd);
                partLinShi.insert(part);
            }
            for (QString vpart : partLinShi)
            {
                if (hsStep.contains(vpart))
                {
                    if (hsf.contains(vpart) && hsf[vpart] != nullptr) {
                        hsf[vpart]->router.append(hsStep[vpart]);
                    }
                }
            }
            if (YXBJ == 1)
            {
                QSet<subFlow *> cSet;
                for (auto it = hsf.begin(); it != hsf.end(); ++it) {
                    if (it.value() != nullptr) {
                        cSet.insert(it.value());
                    }
                }
                children.append(cSet);
                YXBJ = 0;
            }
        }
    }
    
    qDebug() << "splitByPart方法执行完成";
    return true;
}

bool subFlow::splitByMerge()
{
    qDebug() << "进入splitByMerge方法";
    //如果每一步都是只有一个工序，那么就没有子流程
    bool conti = false;
    QSet <int> flowSeq;//当前流程的所有工序序号
    QList<QSet<CJgDepandency*> *> routerBuff;//复制一下数据
    for (QSet<CJgDepandency*>* psd : router)
    {
        if (psd == nullptr) continue;
        
        if (psd->count() > 1)
        {
            conti = true;
        }
        QSet<CJgDepandency*>* ns = new QSet<CJgDepandency*>;
        for (CJgDepandency* pd : *psd)
        {
            if (pd == nullptr) continue;
            
            ns->insert(pd);
            if (pd->curProcess)
            {
                flowSeq.insert(pd->curProcess->miPartSeqNum);
            }
        }
        routerBuff.append(ns);
    }
    if (conti == false)
    {
        for (QSet<CJgDepandency*>* psd : routerBuff)
        {
            delete psd;
        }
        qDebug() << "没有需要合并的流程，splitByMerge方法执行完成";
        return true;
    }

    QHash<int, subFlow *> hsf;//子流程集合，还未保存到本流程的子流程集合列表，
    QHash<int, QSet<int>> hsSeq;//每个分支所包含的后续工序序号的集合,包含合并后的
    QHash<int, QSet<int>> hsDoneSeq;//每个分支已经收录的工序序号，完成一个段落后清空
    QSet<int> setFirstSeq;//上面每个分支的索引
    QSet<int> psyFirstSeq;//子流程集合实际的开始工序包括复线子流程被合并的工序
    QSet<int> setLastSeq;//本流程所有没有后续的流程，

    //本流程的最后工序只需要计算一次
    for (QSet<CJgDepandency*>* psd : router)
    {
        if (psd == nullptr) continue;
        
        for (CJgDepandency* pd : *psd)
        {
            if (pd == nullptr) continue;
            
            QSet<int> sb;
            for (CJgOrderProcess * pOp : pd->DirectTo)
            {
                if (pOp != nullptr) {
                    sb.insert(pd->curProcess->miPartSeqNum);
                }
            }
            sb.intersect(flowSeq);
            if (sb.count() == 0)
            {
                if (pd->curProcess)
                {
                    setLastSeq.insert(pd->curProcess->miPartSeqNum);
                }
            }
        }
    }

    //qDebug() << "最后工序" << setLastSeq;

    //增加本流程子流程集合列表一个记录的子函数

    // 添加迭代计数器，防止死循环
    int iterationCount = 0;
    const int maxIterations = 1000; // 最大迭代次数限制

    for (QSet<CJgDepandency*>* psd : routerBuff)
    {
        // 检查迭代次数，防止死循环
        if (++iterationCount > maxIterations) {
            qDebug() << "警告：splitByMerge达到最大迭代次数，防止死循环退出";
            break;
        }

        if (psd == nullptr) continue;
        
        QHash<int, QSet<CJgDepandency*>*>hsStep;//在一个步骤过程中各个分支分到的工序，在步骤完成后加入到hsf的router并清除
        bool newSubFlowStep = false;
        QSet<int> StepSeqNew;
        QMap<int, int> seq2Key;//当前工序到索引的映射

        if ((setFirstSeq.count() == 1) && (psyFirstSeq.count() == 1) && (psd->count() > 1))
        {
            QSet<int> CN;
            for (CJgDepandency* pd : *psd)
            {
                if (pd == nullptr) continue;
                
                CN.insert(pd->curProcess->miPartSeqNum);
                for (CJgOrderProcess * pOp : pd->AllTo)
                {
                    if (pOp != nullptr) {
                        CN.insert(pOp->miPartSeqNum);
                    }
                }
            }
            CN.intersect(setLastSeq);
            if (CN.count() == setLastSeq.count())
            {
                newSubFlowStep = true;
            }
        }

        if ((setFirstSeq.count() > 1) && (psd->count() > 1))
        {
            //5、例如2依赖0，3依赖1/2，4依赖1/2，这种情况分为1/2一个段落和3/4一个段落，1/2并行，3/4并行，特点是每个分支的前置是所有的done
            bool duoduoduo = true;
            QSet<int> CNDONE;
            for (auto it = hsDoneSeq.begin(); it != hsDoneSeq.end(); ++it) {
                CNDONE.unite(*it);
            }
            //qDebug() << "CNDONE" << CNDONE;
            for (CJgDepandency* pd : *psd)
            {
                if (pd == nullptr) continue;
                
                QSet<int> CN;
                for (CJgOrderProcess * pOp : pd->AllFrom)
                {
                    if (pOp != nullptr) {
                        CN.insert(pOp->miPartSeqNum);
                    }
                }
                CN.intersect(flowSeq);
                if (CN != CNDONE)
                {
                    //qDebug() << "CN" << CN;
                    duoduoduo = false;
                    break;
                }
            }

            if (duoduoduo)
            {
                newSubFlowStep = true;
            }
        }

        for (CJgDepandency* pd : *psd)
        {
            if (pd == nullptr) continue;
            
            //qDebug() << pd->Desp();
            int iKey = 0;//当前分支索引
            int iSeq = pd->curProcess->miPartSeqNum;
            if (newSubFlowStep == false)
            {
                //已经确定要开新段落，不用在旧的分支里面找
                for (int vKey : setFirstSeq)
                {
                    if (hsSeq.contains(vKey) && hsSeq[vKey].contains(iSeq))
                    {
                        //要放在步数最长的一个路径里
                        if (iKey == 0)
                        {
                            iKey = vKey;
                        }
                        else if (hsf.contains(vKey) && hsf.contains(iKey) && 
                                 hsf[vKey] != nullptr && hsf[iKey] != nullptr &&
                                 hsf[vKey]->router.count() > hsf[iKey]->router.count())
                        {
                            iKey = vKey;
                        }
                    }
                }
            }
            seq2Key[iSeq] = iKey;
            StepSeqNew.insert(iSeq);
            if (iKey == 0)
            {
                //不在分支内，必定是要创建新分支
                newSubFlowStep = true;
                QSet<CJgDepandency*> *pSD = new QSet<CJgDepandency*>;
                hsStep[iSeq] = pSD;
                hsStep[iSeq]->insert(pd);
            }
            else
            {
                if (false == hsStep.contains(iKey))
                {
                    QSet<CJgDepandency*> *pSD = new QSet<CJgDepandency*>;
                    hsStep[iKey] = pSD;
                }
                hsStep[iKey]->insert(pd);
            }
        }

        //判断要不要合并分支，任意一个工序如果是最后工序，需要判断他所在的分支是否与其他分支有交集，有的话进行合并
        if (false == newSubFlowStep)
        {
            for (int iSeq : StepSeqNew)
            {
                int iKey = seq2Key[iSeq];
                if (!setFirstSeq.contains(iKey))
                {
                    continue;//已经在其他时候被合并了
                }
                QSet<int> isRemoveKey;
                for (int vKey : setFirstSeq)
                {
                    if (vKey == iKey)
                    {
                        continue;
                    }
                    if (hsSeq.contains(vKey) && hsSeq[vKey].contains(iSeq))
                    {
                        //合并分支
                        isRemoveKey.insert(vKey);
                        if (hsf.contains(vKey) && hsf.contains(iKey) && 
                            hsf[vKey] != nullptr && hsf[iKey] != nullptr) {
                            for (int iv = 0; iv < hsf[vKey]->router.count(); iv++)
                            {
                                QSet<CJgDepandency*>* psdv = hsf[vKey]->router.at(iv);
                                if (hsf[iKey]->router.count() > iv)
                                {
                                    hsf[iKey]->router.at(iv)->unite(*psdv);
                                }
                                else
                                {
                                    hsf[iKey]->router.append(new QSet<CJgDepandency*>);
                                    hsf[iKey]->router.at(iv)->unite(*psdv);
                                }
                            }
                            delete hsf[vKey];
                            hsf.remove(vKey);
                        }
                        if (hsSeq.contains(vKey))
                        {
                            if (hsSeq.contains(iKey)) {
                                hsSeq[iKey].unite(hsSeq[vKey]);
                            }
                        }
                        hsSeq.remove(vKey);
                        if (hsStep.contains(vKey) && hsStep.contains(iKey))
                        {
                            hsStep[iKey]->unite(*hsStep[vKey]);
                        }
                        if (hsStep.contains(vKey)) {
                            delete hsStep[vKey];
                            hsStep.remove(vKey);
                        }
                        if (hsDoneSeq.contains(vKey)) {
                            if (hsDoneSeq.contains(iKey)) {
                                hsDoneSeq[iKey].unite(hsDoneSeq[vKey]);
                            }
                            hsDoneSeq.remove(vKey);
                        }
                    }
                }
                setFirstSeq.subtract(isRemoveKey);
                isRemoveKey.clear();
            }
        }

        //判断要不要合并分支，任意一个工序如果是最后工序，需要判断他所在的分支是否与其他分支有交集，有的话进行合并
        if (false == newSubFlowStep)
        {
            for (int iSeq : StepSeqNew)
            {
                int iKey = seq2Key[iSeq];
                if (!setFirstSeq.contains(iKey))
                {
                    continue;//已经在其他时候被合并了
                }
                QSet<int> isRemoveKey;
                for (int vKey : setFirstSeq)
                {
                    if (vKey == iKey)
                    {
                        continue;
                    }
                    QSet<int> isb;
                    if (hsSeq.contains(iKey) && hsSeq.contains(vKey)) {
                        isb = hsSeq[iKey];
                        if (isb.intersect(hsSeq[vKey]).count() > 0)
                        {
                            //合并分支
                            isRemoveKey.insert(vKey);
                            if (hsf.contains(vKey) && hsf.contains(iKey) && 
                                hsf[vKey] != nullptr && hsf[iKey] != nullptr) {
                                for (int iv = 0; iv < hsf[vKey]->router.count(); iv++)
                                {
                                    QSet<CJgDepandency*>* psdv = hsf[vKey]->router.at(iv);
                                    if (hsf[iKey]->router.count() > iv)
                                    {
                                        hsf[iKey]->router.at(iv)->unite(*psdv);
                                    }
                                    else
                                    {
                                        hsf[iKey]->router.append(new QSet<CJgDepandency*>);
                                        hsf[iKey]->router.at(iv)->unite(*psdv);
                                    }
                                }
                                delete hsf[vKey];
                                hsf.remove(vKey);
                            }
                            if (hsSeq.contains(vKey))
                            {
                                if (hsSeq.contains(iKey)) {
                                    hsSeq[iKey].unite(hsSeq[vKey]);
                                }
                            }
                            hsSeq.remove(vKey);
                            if (hsStep.contains(vKey) && hsStep.contains(iKey))
                            {
                                hsStep[iKey]->unite(*hsStep[vKey]);
                            }
                            if (hsStep.contains(vKey)) {
                                delete hsStep[vKey];
                                hsStep.remove(vKey);
                            }
                            if (hsDoneSeq.contains(vKey)) {
                                if (hsDoneSeq.contains(iKey)) {
                                    hsDoneSeq[iKey].unite(hsDoneSeq[vKey]);
                                }
                                hsDoneSeq.remove(vKey);
                            }
                        }
                    }
                }
                setFirstSeq.subtract(isRemoveKey);
                isRemoveKey.clear();
            }

        }


        if (newSubFlowStep)
        {
            //旧hsf加入children
            if (hsf.count() > 0)
            {
                QSet<subFlow *> cSet;
                for (auto it = hsf.begin(); it != hsf.end(); ++it) {
                    if (it.value() != nullptr) {
                        cSet.insert(it.value());
                    }
                }
                children.append(cSet);
                hsf.clear();
            }
            for (auto it = hsDoneSeq.begin(); it != hsDoneSeq.end(); ++it) {
                flowSeq.subtract(*it);
            }
            hsDoneSeq.clear();
            setFirstSeq.clear();
            psyFirstSeq.clear();
            hsSeq.clear();

            //建立新段落的数据
            QSet<int> finalComm = flowSeq;
            QSet<int> oneOp;

            for (int start : StepSeqNew)
            {
                setFirstSeq.insert(start);
                psyFirstSeq.insert(start);
                subFlow * f = new subFlow(this);
                if (f != nullptr) {
                    hsf[start] = f;
                }
                oneOp.clear();
                if (hsStep.contains(start))
                {
                    for (CJgDepandency* pd : *hsStep[start])
                    {
                        if (pd == nullptr) continue;
                        
                        oneOp.insert(pd->curProcess->miPartSeqNum);
                        for (CJgOrderProcess * pOp :  pd->AllTo)
                        {
                            if (pOp != nullptr) {
                                oneOp.insert(pOp->miPartSeqNum);
                            }
                        }
                    }
                }
                oneOp.intersect(flowSeq);
                hsSeq[start] = oneOp;
                finalComm.intersect(oneOp);
            }
            //处理问题240621：增加对finalComm每个元素的检查，必须包含了hsSeq的每个元素作为前置才可以
            bool decFinal = true;
            while (decFinal)
            {
                decFinal = false;
                for (int iInFanal :  finalComm)
                {
                    CJgDepandency* pd = getDepandcyBySeq(iInFanal);
                    if (pd == nullptr)
                    {
                        decFinal = true;
                        finalComm.remove(iInFanal);
                        break;
                    }
                    QSet<int> dfrom;
                    for (CJgOrderProcess * pOp : pd->AllFrom)
                    {
                        if (pOp != nullptr) {
                            dfrom.insert(pOp->miPartSeqNum);
                        }
                    }
                    bool hsSeqAllInFinal = true;
                    for (int k : setFirstSeq)
                    {
                        QSet<int> seqByKey;
                        if (hsSeq.contains(k)) {
                            seqByKey = hsSeq[k];
                        }
                        seqByKey.subtract(finalComm);
                        //qDebug() << seqByKey;
                        for (int seq : seqByKey)
                        {
                            if (!dfrom.contains(seq))
                            {
                                decFinal = true;
                                finalComm.remove(iInFanal);
                                hsSeqAllInFinal = false;
                                break;
                            }
                        }
                        if (hsSeqAllInFinal == false)
                        {
                            break;
                        }
                    }
                    if (hsSeqAllInFinal == false)
                    {
                        break;
                    }
                }
            }
            //qDebug() << finalComm;

            if (StepSeqNew.count() > 1)
            {
                for (int start : StepSeqNew)
                {
                    if (hsSeq.contains(start)) {
                        hsSeq[start].subtract(finalComm);
                    }
                }
            }
            if (finalComm.count() > 0)
            {
                //如果出现有共同后继，但是中间某个分支又有提前结束的工序，整段合并为一个流程
                bool stopAndComm = false;
                QSet<int> buf;
                for (int vKey : StepSeqNew)
                {
                    if (hsSeq.contains(vKey)) {
                        buf = hsSeq[vKey];
                    }
                    buf.intersect(setLastSeq);
                    if (buf.count() > 0)
                    {
                        stopAndComm = true;
                        break;
                    }
                }
                if (stopAndComm)
                {
                    //所有的没有做的，都放到一个流程里面
                    buf = finalComm;
                    int iKey = 0;
                    for (int vKey : StepSeqNew)
                    {
                        if (hsSeq.contains(vKey)) {
                            buf.unite(hsSeq[vKey]);
                        }
                        iKey = vKey;
                    }
                    for (int vKey : StepSeqNew)
                    {
                        if (iKey == vKey)
                        {
                            if (hsSeq.contains(iKey)) {
                                hsSeq[iKey].unite(buf);
                            }
                        }
                        else
                        {
                            if (hsf.contains(vKey)) {
                                delete hsf[vKey];
                                hsf.remove(vKey);
                            }
                            setFirstSeq.remove(vKey);
                            //psyFirstSeq.remove(vKey);
                            if (hsStep.contains(iKey) && hsStep.contains(vKey)) {
                                hsStep[iKey]->unite(*hsStep[vKey]);
                            }
                            if (hsStep.contains(vKey)) {
                                delete hsStep[vKey];
                                hsStep.remove(vKey);
                            }
                        }
                    }
                    StepSeqNew.clear();
                    StepSeqNew.insert(iKey);
                }
            }
        }
        //hsStep加入hsf,如果没有就创建
        for (int vKey : setFirstSeq)
        {
            if (hsStep.contains(vKey))
            {
                if (hsf.contains(vKey) && hsf[vKey] != nullptr) {
                    hsf[vKey]->router.append(hsStep[vKey]);
                }
            }
        }
        for (int iSeq : StepSeqNew)
        {
            for (int iKey : setFirstSeq)
            {
                if (hsSeq.contains(iKey) && hsSeq[iKey].contains(iSeq))
                {
                    if (hsDoneSeq.contains(iKey)) {
                        hsDoneSeq[iKey].insert(iSeq);
                    }
                }
            }
        }

    }
    //旧hsf加入children，如果总共只有一个就不用加入
    if (children.count() > 0 || hsf.count() > 1)
    {
        QSet<subFlow *> cSet;
        for (auto it = hsf.begin(); it != hsf.end(); ++it) {
            if (it.value() != nullptr) {
                cSet.insert(it.value());
            }
        }
        children.append(cSet);
        hsf.clear();
    }
    else
    {
        //清除数据
        for (auto it = hsf.begin(); it != hsf.end(); ++it) {
            if (it.value() != nullptr) {
                delete it.value();
            }
        }
        children.clear();
    }

    for (QSet<CJgDepandency*>* psd : routerBuff)
    {
        delete psd;
    }
    
    qDebug() << "splitByMerge方法执行完成";
    return true;
}


bool subFlow::getSTD()
{
    if (children.count() == 0)
    {
        for (QSet<CJgDepandency*> *psd : router)
        {
            if (psd == nullptr) continue;
            float fMax = 0.0;
            for (CJgDepandency* pd : *psd)
            {
                if (pd == nullptr) continue;
                if (pd->curProcess && pd->curProcess->mfProcessStdTime)
                {
                    if (pd->curProcess->miProcessAttri == 0)
                    {
                        fMax += pd->curProcess->mfProcessStdTime;
                    }
                }
            }
            totalSTD += fMax;
        }
        return true;
    }
    totalSTD = 0;
    QString s;
    for (QSet<subFlow *> fs : children)
    {
        if (fs.isEmpty()) continue;
        float fMax = 0.0;
        for (subFlow * f : fs)
        {
            if (f == nullptr) continue;
            f->getSTD();
            if (s != f->partName)
            {
                if (fMax < f->totalSTD)
                {
                    fMax = f->totalSTD;
                }
                s = f->partName;
            }
            else
            {
                fMax += f->totalSTD;
            }
        }
        totalSTD += fMax;
    }
    return true;
}

bool subFlow::setTime(int iStart, int iEnd, int iCnt, float fRate)
{
    iStartSec = iStart;
    iEndSec = iEnd;
    iAvgCnt = iCnt;
    // 防止负数和除零错误
    if (totalSTD < 0) totalSTD = 0;
    if (fRate < 0) fRate = 0;
    if (iCnt < 0) iCnt = 0;
    
    iFirstBox = totalSTD * iAvgCnt * fRate;
    if (iFirstBox > (iEndSec - iStartSec))
    {
        iFirstBox = iEndSec - iStartSec;
    }
    
    // 确保iFirstBox不为负数
    if (iFirstBox < 0) iFirstBox = 0;
    
    if (children.count() == 0)
    {
        return true;
    }
    
    float LeftTime = iEnd - iStart - iFirstBox;
    // 确保LeftTime不为负数
    if (LeftTime < 0) LeftTime = 0;
    
    int offSetTime = 0;
    for (QSet<subFlow *> fs : children)
    {
        if (fs.isEmpty()) continue;
        float fMax = 0.0;
        for (subFlow * f : fs)
        {
            if (f == nullptr) continue;
            if (fMax < f->totalSTD)
            {
                fMax = f->totalSTD;
            }
        }
        int i = 0;
        if (totalSTD > 0)  // 防止除零错误
        {
            i = iFirstBox * fMax / totalSTD;
        }
        for (subFlow * f : fs)
        {
            if (f == nullptr) continue;
            f->setTime(offSetTime + iStartSec, offSetTime + iStartSec + i + LeftTime, iAvgCnt, fRate);
        }
        offSetTime += i;
    }
    return true;
}

bool subFlow::outProcessTime(int OrderCnt, qlonglong nowSec)
{
    qDebug() << "进入outProcessTime方法，订单数量:" << OrderCnt << "，当前时间:" << nowSec;
    if (children.count() > 0)
    {
        qDebug() << "处理子流程，子流程数量:" << children.size();
        for (QSet<subFlow *> fs : children)
        {
            if (fs.isEmpty()) continue;
            for (subFlow * f : fs)
            {
                if (f != nullptr) {
                    qDebug() << "递归调用子流程outProcessTime";
                    f->outProcessTime(OrderCnt, nowSec);
                } else {
                    qDebug() << "发现空的子流程指针，跳过";
                }
            }
        }
        qDebug() << "子流程处理完成";
        return true;
    }

    // 确保时间值有效
    if (iStartSec < 0) iStartSec = 0;
    if (iEndSec < 0) iEndSec = 0;
    if (iFirstBox < 0) iFirstBox = 0;
    
    float LeftTime = iEndSec - iStartSec - iFirstBox;
    // 确保LeftTime不为负数
    if (LeftTime < 0) LeftTime = 0;

    //计算每道工序前面的依赖时间
    QSet <int> flowSeq;
    qDebug() << "计算工序依赖时间，router数量:" << router.size();
    for (QSet<CJgDepandency*>* psd : router)
    {
        if (psd == nullptr) {
            qDebug() << "发现空的依赖步骤指针，跳过";
            continue;
        }
        for (CJgDepandency* pd : *psd)
        {
            if (pd == nullptr || pd->curProcess == nullptr) {
                qDebug() << "发现空的依赖对象或工序指针，跳过";
                continue;
            }
            flowSeq.insert(pd->curProcess->miPartSeqNum);
        }
    }
    
    for (QSet<CJgDepandency*>* psd : router)
    {
        if (psd == nullptr) {
            qDebug() << "发现空的依赖步骤指针，跳过";
            continue;
        }
        for (CJgDepandency* pd : *psd)
        {
            if (pd == nullptr) {
                qDebug() << "发现空的依赖对象指针，跳过";
                continue;
            }
            pd->FromSTD = 0;
            if (pd->AllFrom.isEmpty()) {
                qDebug() << "工序无前置依赖";
            }
            for (CJgOrderProcess * pOp : pd->AllFrom)
            {
                if (pOp != nullptr && flowSeq.contains(pOp->miPartSeqNum))
                {
                    if (pOp->miProcessAttri == 0)
                    {
                        pd->FromSTD += pOp->mfProcessStdTime;
                    }
                }
            }
        }
    }

    qDebug() << "处理工序计划，router数量:" << router.size();
    for (QSet<CJgDepandency*>* psd : router)
    {
        if (psd == nullptr) {
            qDebug() << "发现空的依赖步骤指针，跳过";
            continue;
        }
        for (CJgDepandency* pd : *psd)
        {
            if (pd == nullptr) {
                qDebug() << "发现空的依赖对象指针，跳过";
                continue;
            }
            
            qDebug() << "处理工序依赖对象";
            int i = 0;
            qDebug() << "检查totalSTD值:" << totalSTD;
            if (totalSTD > 0)  // 防止除零错误
            {
                if (pd->curProcess) {
                    qDebug() << "工序ID:" << pd->curProcess->miPartSeqNum 
                             << "，工序属性:" << pd->curProcess->miProcessAttri
                             << "，标准时间:" << pd->curProcess->mfProcessStdTime;
                    if (pd->curProcess->miProcessAttri == 0)
                    {
                        i = iFirstBox * pd->curProcess->mfProcessStdTime / totalSTD;
                    }
                    else
                    {
                        i = 0;
                    }
                } else {
                    qDebug() << "当前工序为空";
                }
            } else {
                qDebug() << "totalSTD为0或负数，跳过计算";
            }
            
            qDebug() << "检查plan对象";
            if (pd->plan == nullptr)
            {
                qDebug() << "创建新的工序计划对象";
                pd->plan = new CJgProcessPlan;
            }
            
            qDebug() << "设置工序计划数据";
            if (pd->curProcess) {
                qDebug() << "检查pOp指针相关对象:";
                qDebug() << "  pd地址:" << pd;
                qDebug() << "  pd->plan地址:" << pd->plan;
                qDebug() << "  pd->curProcess地址:" << pd->curProcess;
                if (pd->plan) {
                    qDebug() << "  pd->plan有效";
                } else {
                    qDebug() << "  pd->plan无效";
                }
                
                qDebug() << "设置pOp指针";
                // 添加安全检查
                if (pd->plan != nullptr && pd->curProcess != nullptr) {
                    pd->plan->pOp = pd->curProcess;
                    qDebug() << "pOp指针设置完成，值为:" << pd->plan->pOp;
                } else {
                    qDebug() << "无法设置pOp指针，plan或curProcess为空";
                    if (!pd->plan) qDebug() << "  plan为空";
                    if (!pd->curProcess) qDebug() << "  curProcess为空";
                    continue;
                }
                
                qDebug() << "设置完成数量";
                pd->plan->iOrderComplete = pd->curProcess->miFinishedCnt;
                qDebug() << "完成数量设置完成:" << pd->plan->iOrderComplete;
                qDebug() << "设置订单总数";
                pd->plan->iOrderTotal = OrderCnt;
                qDebug() << "订单总数设置完成:" << pd->plan->iOrderTotal;
                qDebug() << "设置工序序号";
                pd->plan->iSeq = pd->curProcess->miPartSeqNum;
                qDebug() << "工序序号设置完成:" << pd->plan->iSeq;
                qDebug() << "工序计划数据设置完成: 工序ID=" << pd->plan->iSeq 
                         << "，订单总数=" << pd->plan->iOrderTotal
                         << "，已完成=" << pd->plan->iOrderComplete;
            } else {
                qDebug() << "工序依赖对象的当前工序为空";
                continue;
            }
            // 确保各项值有效
            if (OrderCnt < 0) OrderCnt = 0;
            if (pd->plan->iOrderComplete < 0) pd->plan->iOrderComplete = 0;
            
            qDebug() << "设置当前时间";
            pd->plan->iNowSec = nowSec;
            qDebug() << "设置时间参数: iStartSec=" << iStartSec 
                     << "，iFirstBox=" << iFirstBox 
                     << "，FromSTD=" << pd->FromSTD 
                     << "，totalSTD=" << totalSTD;
            //plan.iStartSec = offSetTime + iStartSec;
            if (totalSTD > 0)  // 防止除零错误
            {
                pd->plan->iStartSec = iStartSec + iFirstBox * pd->FromSTD / totalSTD;
            }
            else
            {
                pd->plan->iStartSec = iStartSec;
            }
            pd->plan->iEndSec = pd->plan->iStartSec + i + LeftTime;
            
            qDebug() << "计算时间参数: StartSec=" << pd->plan->iStartSec 
                     << "，EndSec=" << pd->plan->iEndSec 
                     << "，NowSec=" << pd->plan->iNowSec;
            
            // 确保时间值有效
            if (pd->plan->iStartSec < 0) pd->plan->iStartSec = 0;
            if (pd->plan->iEndSec < 0) pd->plan->iEndSec = 0;
            if (pd->plan->iNowSec < 0) pd->plan->iNowSec = 0;
            
            //offSetTime += i;
            if (pd->plan->iNowSec >= pd->plan->iEndSec)
            {
                pd->plan->iPlanNow = pd->plan->iOrderTotal;
            }
            else if (pd->plan->iNowSec <= pd->plan->iStartSec)
            {
                pd->plan->iPlanNow = 0;
            }
            else if (pd->plan->iEndSec == pd->plan->iStartSec)
            {
                pd->plan->iPlanNow = pd->plan->iOrderTotal;
            }
            else
            {
                // 防止除零错误
                qlonglong timeDiff = pd->plan->iEndSec - pd->plan->iStartSec;
                qDebug() << "计算计划数量: timeDiff=" << timeDiff;
                if (timeDiff > 0) {
                    pd->plan->iPlanNow = pd->plan->iOrderTotal * (pd->plan->iNowSec - pd->plan->iStartSec) / timeDiff;
                } else {
                    pd->plan->iPlanNow = pd->plan->iOrderTotal;
                }
            }
            
            // 确保计划数量有效
            if (pd->plan->iPlanNow < 0) pd->plan->iPlanNow = 0;
            if (pd->plan->iOrderTotal < 0) pd->plan->iOrderTotal = 0;
            
            qDebug() << "最终计划数量: PlanNow=" << pd->plan->iPlanNow;
            
            if (pd->plan->pOp)
            {
                qDebug() << "检查工序是否正常";
                if (pd->plan->pOp->IsNormal())//(plan.pOp->mProcessBrief != SECONDPACKUP_PROCESS)
                {
                    qDebug() << "处理正常工序";
                    //int todocount = 0;//用来计算加减人的小时件数
                    qlonglong timeDiff = pd->plan->iEndSec - pd->plan->iStartSec;
                    qDebug() << "计算小时任务数: timeDiff=" << timeDiff;
                    if (timeDiff > 0)
                    {
                        pd->plan->pOp->mScheduling->mPlanHourTarget = pd->plan->iOrderTotal * 3600.0 / timeDiff;
                    }
                    else
                    {
                        pd->plan->pOp->mScheduling->mPlanHourTarget = pd->plan->iOrderTotal;
                    }
                    
                    // 确保目标值有效
                    if (pd->plan->pOp->mScheduling->mPlanHourTarget < 0) 
                        pd->plan->pOp->mScheduling->mPlanHourTarget = 0;
                    
                    qDebug() << "计划小时任务数:" << pd->plan->pOp->mScheduling->mPlanHourTarget;
                    
                    if (pd->plan->iPlanNow > pd->plan->iOrderComplete)
                    {
                        if (pd->plan->iNowSec <= pd->plan->iEndSec)
                        {
                            pd->plan->pOp->mScheduling->mNowHourTarget = (pd->plan->iPlanNow - pd->plan->iOrderComplete) / gRuleHourTargetWindow;
                        }
                        else
                        {
                            int miaoshu = gRuleHourTargetWindow * 3600 - pd->plan->iNowSec + pd->plan->iEndSec;
                            qDebug() << "计算当前小时任务数: miaoshu=" << miaoshu;
                            if (miaoshu > 3600)
                            {
                                pd->plan->pOp->mScheduling->mNowHourTarget = (pd->plan->iPlanNow - pd->plan->iOrderComplete) * 3600 / miaoshu;
                            }
                            else
                            {
                                pd->plan->pOp->mScheduling->mNowHourTarget = (pd->plan->iPlanNow - pd->plan->iOrderComplete);
                            }
                        }
                        // 确保目标值有效
                        if (pd->plan->pOp->mScheduling->mNowHourTarget < 0) 
                            pd->plan->pOp->mScheduling->mNowHourTarget = 0;
                    }
                    else
                    {
                        //plan.pOp->mScheduling->mNowHourTarget = 0;
                        //todocount = plan.iPlanNow - plan.iOrderComplete;//负数不需要除以gRuleHourTargetWindow，因为已经提前了好几个小时了，本应乘以gRuleHourTargetWindow又会太大
                        if (pd->plan->pOp->mbCompletedFlag)
                        {
                            pd->plan->pOp->mScheduling->mNowHourTarget = 0;
                        }
                        else
                        {
                            pd->plan->pOp->mScheduling->mNowHourTarget = pd->plan->iPlanNow - pd->plan->iOrderComplete;//直接带出负数
                        }
                    }
                    qDebug() << "当前小时任务数:" << pd->plan->pOp->mScheduling->mNowHourTarget;
                }
                else
                {
                    qDebug() << "处理非正常工序";
                    if (pd->plan->pOp->mScheduling) {
                        pd->plan->pOp->mScheduling->mNowHourTarget = 0;
                        pd->plan->pOp->mScheduling->mPlanHourTarget = 0;
                        qDebug() << "非正常工序，小时任务数设为0";
                    }
                }
            }
            else
            {
                qDebug() << "没有工序";
            }
        }
    }
    qDebug() << "outProcessTime方法执行完成";
    return true;
}

CJgDepandency * subFlow::getDepandcyBySeq(int vSeq)
{
    CJgDepandency * rp = nullptr;
    for (QSet<CJgDepandency*> * psd : router)
    {
        for (CJgDepandency* vrp : *psd)
        {
            if (vrp->curProcess)
            {
                if (vrp->curProcess->miPartSeqNum == vSeq)
                {
                    rp = vrp;
                    return rp;
                }
            }
        }
    }
    return rp;
}

float subFlow::getMaxSTDbyProcess()
{
    float fMax = 0;
    for (QSet<CJgDepandency*> * psd : router)
    {
        for (CJgDepandency* vrp : *psd)
        {
            if (vrp->curProcess)
            {
                if (vrp->curProcess->mfProcessStdTime > fMax)
                {
                    fMax = vrp->curProcess->mfProcessStdTime;
                }
            }
        }
    }
    return fMax;
}

//拿到这个流程下按照工序计算的最小做工时间，需要递归调用且在outProcessTime调用过之后
int subFlow::getMinOperationTimeByProcess()
{
    int iMin = 0;
    if (children.count() > 0)
    {
        for (QSet<subFlow *> fs : children)
        {
            for (subFlow * f : fs)
            {
                int ibuf = f->getMinOperationTimeByProcess();
                if ((ibuf != 0) && ((ibuf < iMin) || (iMin == 0)))
                {
                    iMin = ibuf;
                }
            }
        }
    }
    else
    {
        for (QSet<CJgDepandency*> * psd : router)
        {
            for (CJgDepandency* vrp : *psd)
            {
                if (vrp->plan)
                {
                    int ibuf = vrp->plan->iEndSec - vrp->plan->iStartSec;
                    if ((ibuf != 0) && ((ibuf < iMin) || (iMin == 0)))
                    {
                        iMin = ibuf;
                    }
                }
            }
        }
    }
    return iMin;
}
